home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 147 / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan).7z / Gekkan Dennou Club - 2000.8 Vol. 147 (Japan) (Track 1).bin / games / hexrev / think.c < prev   
C/C++ Source or Header  |  2000-06-25  |  18KB  |  731 lines

  1. /***************************************************
  2.  
  3.   think.c : 六角リバーシ思考ルーチン
  4.  
  5.         Copyright (C) 1997 - 2000 by Makoto Hiroi
  6.  
  7. ****************************************************/
  8. #include  "hexrev.h"
  9.  
  10. /* 関数宣言 */
  11. static int search_white( int, int, int );
  12. static int finish_white( int, int );
  13.  
  14. extern const char  reverse_table[546][11];
  15. extern const short zahyou[SIZE][2];
  16.  
  17. /* 盤面の定義 */
  18. static char  board[SIZE];
  19. static short black;
  20. static short white;
  21. static int   space[SIZE];          /* 探索領域をセットする */
  22. static int   space_count;          /* カウンタ */
  23. static int   value_table[SIZE];    /* 評価値をセットする */
  24. static int   depth;                /* 探索手数 */
  25.  
  26. static int  w1;      /* 位置数の重み */
  27. static int  w2;      /* 場所の重み */
  28.  
  29. /* 初期化データ */
  30. static const char    init_table[SIZE] = {
  31.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  32.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  33.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  34.   FREE, FREE, FREE, FREE, WHITE, BLACK, FREE,  FREE, FREE, FREE,
  35.   FREE, FREE, FREE, FREE, BLACK, BLACK, WHITE, FREE, FREE, FREE,
  36.   FREE, FREE, FREE, FREE, FREE,  WHITE, BLACK, FREE, FREE, FREE,
  37.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  38.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  39.   FREE, FREE, FREE, FREE, FREE,  FREE,  FREE,  FREE, FREE, FREE,
  40.   FREE,
  41. };
  42.  
  43. /* 石数の表示 */
  44. void print_stones( void )
  45. {
  46.     _dos_c_locate( 22, 1 );
  47.     printf( "黒 %2d 個 : 白 %2d 個", black, white );
  48.     fflush( stdout );
  49. }
  50.  
  51. /* データの初期化 */
  52. void init_data( void )
  53. {
  54.     int        i;
  55.     const char    *ptr = init_table;
  56.     for( i = 0; i < SIZE; i++, ptr++ ){
  57.           board[i] = *ptr;
  58.     }
  59.     white = 3;
  60.     black = 4;
  61.     /* 駒を置く */
  62.     _iocs_apage( 0 );
  63.     _iocs_wipe();        /* グラフィッククリア */
  64.     draw_piece( 34, WHITE );
  65.     draw_piece( 35, BLACK );
  66.     draw_piece( 44, BLACK );
  67.     draw_piece( 45, BLACK );
  68.     draw_piece( 46, WHITE );
  69.     draw_piece( 55, WHITE );
  70.     draw_piece( 56, BLACK );
  71.     /* 石数の表示 */
  72.     print_stones();
  73. }
  74.  
  75. /* 駒を裏返すことができるか */
  76. int check_reverse( int num )
  77. {
  78.   int    i, result = 0;
  79.   /* 6 方向をチェックする */
  80.   for( i = 0; i < DIR; i++ ){
  81.     int wc = 0, bc = 0, wf = FALSE, bf = FALSE;
  82.     const char  *ptr = reverse_table[num * DIR + i];
  83.     if( *ptr == -1 ) break;        /* 終了 */
  84.     do {
  85.       char content = board[*ptr];
  86.       if( content == FREE ){
  87.         break;            /* 空きエリア */
  88.       } else if( content == BLACK ){
  89.         bf = TRUE;
  90.     if( !wf ) wc++;
  91.       } else {
  92.     wf = TRUE;
  93.         if( !bf ) bc++;
  94.       }
  95.     } while( *(++ptr) != -1 );
  96.     if( bf && bc ) result |= PUT_BLACK;
  97.     if( wf && wc ) result |= PUT_WHITE;
  98.     if( result == (PUT_BLACK|PUT_WHITE) ) break;
  99.   }
  100.   return result;
  101. }
  102.  
  103. /* 石を置ける場所をセットする */
  104. static int set_space_postion( void )
  105. {
  106.   int    i, c;
  107.   for( i = c = 0; i < SIZE; i++ ){
  108.     if( board[i] == FREE ){
  109.       space[c] = i;
  110.       value_table[c++] = NO_VALUE;
  111.     }
  112.   }
  113.   return space_count = c;
  114. }
  115.  
  116. /* 駒を置ける場所をセットする */
  117. static int set_piece_postion( void )
  118. {
  119.     int  i, c;
  120.     for( i = c = 0; i < SIZE; i++ ){
  121.         if( board[i] == FREE ){
  122.             space[c] = i;
  123.             value_table[c++] = NO_VALUE;
  124.         }
  125.     }
  126.     return c;
  127. }
  128.  
  129.  
  130. /* 座標から位置を求める */
  131. int get_postion( int x, int y )
  132. {
  133.     int  i, j = set_piece_postion();
  134.     for( i = 0; i < j; i++ ){
  135.         int  n = space[i];
  136.         int  x1 = zahyou[n][0];
  137.         int  y1 = zahyou[n][1];
  138.         if( (x1 - 17 <= x) && (x <= x1 + 17) &&
  139.             (y1 - 17 <= y) && (y <= y1 + 17)){
  140.             return n;
  141.         }
  142.     }
  143.     return -1;
  144. }
  145.  
  146.  
  147. /* 指し手があるか */
  148. int check_move( int piece )
  149. {
  150.   int  i;
  151.   int  k = (piece == BLACK) ? PUT_BLACK : PUT_WHITE;
  152.   for( i = 0; i < SIZE; i++ ){
  153.     if( board[i] != FREE ) continue;
  154.     if( check_reverse( i ) & k ) return TRUE;
  155.   }
  156.   return FALSE;
  157. }
  158.  
  159. /* 駒を反転する */
  160. int reverse_piece( int num, int piece, char *result )
  161. {
  162.   int    i, count = 0;
  163.   if( board[num] != FREE ) return 0; /* 石を置くことはできないよ */
  164.   /* 6 方向をチェックする */
  165.   for( i = 0; i < DIR; i++ ){
  166.     int  c = count, flag = FALSE;
  167.     const char *ptr = &(reverse_table[num * DIR + i][0]);
  168.     if( *ptr == -1 ) break;
  169.     do {
  170.       int content = board[*ptr];
  171.       if( content == FREE ){
  172.     break;            /* 空きエリア */
  173.       } else if( content == piece ){
  174.     flag = TRUE; break;    /* 同種の駒を見つけたよ */
  175.       } else {
  176.     result[c++] = *ptr;    /* 異種の駒 */
  177.       }
  178.     } while( *(++ptr) != -1 );
  179.  
  180.     if( flag && (c > count) ){
  181.       count = c;        /* 裏返しができたよ */
  182.     }
  183.   }
  184.   result[count] = -1;           /* 終端セット */
  185.   if( count ){            /* 駒を置くことができるよ */
  186.     board[num] = piece;
  187.     for( i = 0; i < count; i++ ){
  188.       board[ result[i] ] = piece;
  189.     }
  190.     if( piece == BLACK ){
  191.       black += count + 1;
  192.       white -= count;
  193.     } else {
  194.       white += count + 1;
  195.       black -= count;
  196.     }
  197.   }
  198.   return count;
  199. }
  200.  
  201. /* 重みテーブル */
  202. static const int weight_table[SIZE] = {
  203.   1000, 20, 20, 20, 20, 1000,
  204.     20,  0,  1,  1,  1,  0, 20,
  205.     20,  1,  1,  1,  1,  1,  1, 20,
  206.     20,  1,  1,  1,  1,  1,  1,  1, 20,
  207.     20,  1,  1,  1,  1,  1,  1,  1,  1, 20,
  208.   1000,  0,  1,  1,  1,  1,  1,  1,  1,  0, 1000,
  209.     20,  1,  1,  1,  1,  1,  1,  1,  1, 20,
  210.     20,  1,  1,  1,  1,  1,  1,  1, 20,
  211.     20,  1,  1,  1,  1,  1,  1, 20,
  212.     20,  0,  1,  1,  1,  0, 20,
  213.   1000, 20, 20, 20, 20, 1000,
  214. };
  215.  
  216. /* 位置テーブル */
  217. #define CORNER 1
  218.  
  219. static const char postion_table[SIZE] = {
  220.   CORNER, 2, 0, 0, 3, CORNER,
  221.   13, 0, 0, 0, 0, 5, 20,
  222.    0, 0, 0, 0, 0, 0, 0, 0, 
  223.    0, 0, 0, 0, 0, 0, 0, 0, 0, 
  224.   21, 0, 0, 0, 0, 0, 0, 0, 0, 29,
  225.   CORNER, 40, 0, 0, 0, 0, 0, 0, 0, 50, CORNER,
  226.   61, 0, 0, 0, 0, 0, 0, 0, 0, 69,
  227.    0, 0, 0, 0, 0, 0, 0, 0, 0,
  228.    0, 0, 0, 0, 0, 0, 0, 0,
  229.   70,85, 0, 0, 0, 90, 77,
  230.   CORNER, 87, 0, 0, 88, CORNER,
  231. };
  232.  
  233. /* 評価関数(黒有利が正となる) */
  234. static int value_func( int turn )
  235. {
  236.   static const char corner[6] = {0, 5, 40, 50, 85, 90 };
  237.   static const char revision[6][3] = {
  238.      7,  1,  6,  11,  4, 12,  41, 30, 51,  49, 39, 60,
  239.     79, 78, 86,  83, 84, 89,
  240.   };
  241.   static const int rev_value[3] = {
  242.     150, 100, 100
  243.   }; 
  244.   int    bv = 0, wv = 0, bc = 0, wc = 0, i;
  245.   for( i = 0; i < SIZE; i++ ){
  246.     switch( board[i] ){
  247.       case BLACK:
  248.         bv += weight_table[i]; break;
  249.       case WHITE:
  250.         wv += weight_table[i]; break;
  251.       case FREE:
  252.     if( weight_table[i] ){
  253.       int put = check_reverse( i );
  254.       if( put & PUT_BLACK ){
  255.         if( turn == BLACK && postion_table[i] == CORNER ){
  256.           bv += 250;
  257.         } else {
  258.           bc++;
  259.         }
  260.       }
  261.       if( put & PUT_WHITE ){
  262.         if( turn == WHITE && postion_table[i] == CORNER ){
  263.           wv += 250;
  264.         } else {
  265.           wc++;
  266.         }
  267.       }
  268.     }
  269.         break;
  270.       }
  271.   }
  272.   /* 隅の補正 */
  273.   for( i = 0; i < 6; i++ ){
  274.     int j;
  275.     int n = corner[i];
  276.     int k = board[n];
  277.     if( k == FREE ){
  278.       /* 隅が空いているよ */
  279.       for( j = 0; j < 3; j++ ){
  280.     int p = revision[i][j];
  281.     int v = rev_value[j];
  282.         switch( board[ p ] ){
  283.           case BLACK:
  284.         if( board[ postion_table[p] ] != BLACK ) wv += v;
  285.             break;
  286.           case WHITE:
  287.         if( board[ postion_table[p] ] != WHITE ) bv += v;
  288.             break;
  289.         }
  290.       }
  291.     } else {
  292.       /* 辺の安定性を評価(まだ不完全) */
  293.       for( j = 0; j < 2; j++ ){
  294.     int  v = 0;
  295.     const char *ptr = reverse_table[n * DIR + j];
  296.     while( *ptr != -1 ){
  297.       if( k != board[*ptr++] ) break;
  298.       v += 90;
  299.     }
  300.     if( v == 450 ) v /= 2;    /* 5 つとも同じ石 */
  301.     if( k == WHITE ) wv += v;
  302.     else             bv += v;
  303.       }
  304.     }
  305.   }
  306.   /* 石数は逆に評価する */
  307.   return (bc - wc) * w1 + (bv - wv) + (white - black) * w2;
  308. }
  309.  
  310. /* 結果判定 */
  311. int result_value( int flag )
  312. {
  313.   int    value;
  314.   int    wc = white;
  315.   int    bc = black;
  316.   if( wc + bc == SIZE || flag == TRUE ){
  317.     if( wc == bc ){
  318.       value = 0;        /* 引き分け */
  319.     } else if( bc > wc ){
  320.       value = MAX_VALUE + bc - wc; /* 黒勝ち */
  321.     } else {
  322.       value = MIN_VALUE + bc - wc; /* 白勝ち */
  323.     }
  324.   } else if( wc == 0 ){
  325.     value = MAX_VALUE + bc;    /* 白全滅 */
  326.   } else if( bc == 0 ){
  327.     value = MIN_VALUE - wc;    /* 黒全滅 */
  328.   } else {
  329.     value = NO_VALUE;        /* 決着がついていないよ */
  330.   }
  331.   return value;
  332. }
  333.  
  334.  
  335. /* ミニマックスによる探索 */
  336. static int search_black( int his, int limit, int pass_flag )
  337. {
  338.   int i, point = MIN_LIMIT;
  339.   short save_white = white;
  340.   short save_black = black;
  341.   if( his == depth ){
  342.     return value_func( BLACK );
  343.   }
  344.   for( i = 0; i < space_count; i++ ){
  345.     int value, pos = space[i];
  346.     char piece_buffer[SIZE/2];
  347.  
  348.     /* 駒が置いてあるかチェックする */
  349.     if( board[pos] != FREE ) continue;
  350.     /* 駒を置く */
  351.     if( !reverse_piece( pos, BLACK, piece_buffer ) ) continue;
  352.  
  353.     /* 終了チェック */
  354.     if( (value = result_value( FALSE )) == NO_VALUE ){
  355.       /* 相手の手番 */
  356.       value = search_white( his + 1, point, FALSE );
  357.     }
  358.     /* 駒を元に戻す */
  359.     {
  360.       char *ptr = piece_buffer;
  361.       board[pos] = FREE;
  362.       white = save_white;
  363.       black = save_black;
  364.       do {
  365.     board[*ptr++] = WHITE;
  366.       } while( *ptr != -1 );
  367.     }
  368.     /* ミニマックス */
  369.     if( value > point ){
  370.       point = value;
  371.     }
  372.     /* αβ枝刈 */
  373.     if( point > limit ){
  374.       break;
  375.     }
  376.   }
  377.   if( point == MIN_LIMIT ){
  378.     /* 打つ手がなかった */
  379.     if( pass_flag == TRUE ){
  380.       /* 相手も打つ手なし */
  381.       point = result_value( TRUE ); /* 終了 */
  382.     } else {
  383.       /* パスだよ */
  384.       point = search_white( his, MIN_LIMIT, TRUE );
  385.     }
  386.   }
  387.   return point;
  388. }
  389.  
  390. /* 白番 */
  391. static int search_white( int his, int limit, int pass_flag )
  392. {
  393.   int   i, point = MAX_LIMIT;
  394.   short save_white = white;
  395.   short save_black = black;
  396.   if( his == depth ){
  397.     return value_func( WHITE );
  398.   }
  399.   for( i = 0; i < space_count; i++ ){
  400.     int value, pos = space[i];
  401.     char piece_buffer[SIZE/2];
  402.  
  403.     /* 駒が置いてあるかチェックする */
  404.     if( board[pos] != FREE ) continue;
  405.     /* 駒を置く */
  406.     if( !reverse_piece( pos, WHITE, piece_buffer ) ) continue;
  407.  
  408.     /* 終了チェック */
  409.     if( (value = result_value( FALSE )) == NO_VALUE ){
  410.       /* 再帰する */
  411.       value = search_black( his + 1, point, FALSE );
  412.     }
  413.     /* 駒を元に戻す */
  414.     {
  415.       char *ptr = piece_buffer;
  416.       board[pos] = FREE;
  417.       white = save_white;
  418.       black = save_black;
  419.       do {
  420.     board[*ptr++] = BLACK;
  421.       } while( *ptr != -1 );
  422.     }
  423.  
  424.     /* ミニマックス */
  425.     if( point > value ){
  426.       point = value;
  427.     }
  428.     /* αβ枝刈 */
  429.     if( point < limit ){
  430.       break;
  431.     }
  432.   }
  433.   if( point == MAX_LIMIT ){
  434.     /* 打つ手がなかった */
  435.     if( pass_flag == TRUE ){
  436.       /* 相手も打つ手なし */
  437.       point = result_value( TRUE ); /* 終了 */
  438.     } else {
  439.       /* パスだよ */
  440.       point = search_black( his, MAX_LIMIT, TRUE );
  441.     }
  442.   }
  443.   return point;
  444. }
  445.  
  446. /* 読み切り専用 */
  447. static int finish_black( int limit, int pass_flag )
  448. {
  449.   int i, point = MIN_LIMIT;
  450.   short save_white = white;
  451.   short save_black = black;
  452.   for( i = 0; i < space_count; i++ ){
  453.     int value, pos = space[i];
  454.     char piece_buffer[SIZE/2];
  455.  
  456.     /* 駒が置いてあるかチェックする */
  457.     if( board[pos] != FREE ) continue;
  458.     /* 駒を置く */
  459.     if( !reverse_piece( pos, BLACK, piece_buffer ) ) continue;
  460.  
  461.     /* 終了チェック */
  462.     if( black + white < SIZE ){
  463.       value = finish_white( point, FALSE );
  464.     } else {
  465.       value = black - white;
  466.     }
  467.     /* 駒を元に戻す */
  468.     {
  469.       char *ptr = piece_buffer;
  470.       board[pos] = FREE;
  471.       white = save_white;
  472.       black = save_black;
  473.       do {
  474.     board[*ptr++] = WHITE;
  475.       } while( *ptr != -1 );
  476.     }
  477.     /* ミニマックス */
  478.     if( value > point ){
  479.       point = value;
  480.     }
  481.     /* αβ枝刈 */
  482.     if( point > limit ){
  483.       break;
  484.     }
  485.   }
  486.   if( point == MIN_LIMIT ){
  487.     /* 打つ手がなかった */
  488.     if( pass_flag == TRUE ){
  489.       /* 相手も打つ手なし */
  490.       point = black - white; /* 終了 */
  491.     } else {
  492.       /* パスだよ */
  493.       point = finish_white( MIN_LIMIT, TRUE );
  494.     }
  495.   }
  496.   return point;
  497. }
  498.  
  499. /* 白番 */
  500. static int finish_white( int limit, int pass_flag )
  501. {
  502.   int   i, point = MAX_LIMIT;
  503.   short save_white = white;
  504.   short save_black = black;
  505.   for( i = 0; i < space_count; i++ ){
  506.     int  value, pos = space[i];
  507.     char piece_buffer[SIZE];
  508.  
  509.     /* 駒が置いてあるかチェックする */
  510.     if( board[pos] != FREE ) continue;
  511.     /* 駒を置く */
  512.     if( !reverse_piece( pos, WHITE, piece_buffer ) ) continue;
  513.  
  514.     /* 終了チェック */
  515.     if( black + white < SIZE ){
  516.       value = finish_black( point, FALSE );
  517.     } else {
  518.       value = black - white;
  519.     }
  520.     /* 駒を元に戻す */
  521.     {
  522.       char *ptr = piece_buffer;
  523.       board[pos] = FREE;
  524.       white = save_white;
  525.       black = save_black;
  526.       do {
  527.     board[*ptr++] = BLACK;
  528.       } while( *ptr != -1 );
  529.     }
  530.  
  531.     /* ミニマックス */
  532.     if( point > value ){
  533.       point = value;
  534.     }
  535.     /* αβ枝刈 */
  536.     if( point < limit ){
  537.       break;
  538.     }
  539.   }
  540.   if( point == MAX_LIMIT ){
  541.     /* 打つ手がなかった */
  542.     if( pass_flag == TRUE ){
  543.       /* 相手も打つ手なし */
  544.       point = black - white;
  545.     } else {
  546.       /* パスだよ */
  547.       point = finish_black( MAX_LIMIT, TRUE );
  548.     }
  549.   }
  550.   return point;
  551. }
  552.  
  553. /* 単純挿入ソート */
  554. static void sort( int limit )
  555. {
  556.   int i, j;
  557.   for( i = 1; i < limit; i++ ){
  558.     int tmp_pos = space[i];
  559.     int tmp_value = value_table[i];
  560.     for( j = i - 1; j >= 0 && tmp_value > value_table[j]; j-- ){
  561.       space[j + 1] = space[j];
  562.       value_table[j + 1] = value_table[j];
  563.     }
  564.     space[j + 1] = tmp_pos;
  565.     value_table[j + 1] = tmp_value;
  566.   }
  567. }
  568.  
  569. static void rsort( int limit )
  570. {
  571.   int i, j;
  572.   for( i = 1; i < limit; i++ ){
  573.     int tmp_pos = space[i];
  574.     int tmp_value = value_table[i];
  575.     for( j = i - 1; j >= 0 && tmp_value < value_table[j]; j-- ){
  576.       space[j + 1] = space[j];
  577.       value_table[j + 1] = value_table[j];
  578.     }
  579.     space[j + 1] = tmp_pos;
  580.     value_table[j + 1] = tmp_value;
  581.   }
  582. }
  583.  
  584. /* 反復深化による探索 */
  585. static void search_move( int turn, int level )
  586. {
  587.   int limit = set_space_postion();
  588.   short save_white = white;
  589.   short save_black = black;
  590.  
  591.   if( level <= 4 ){
  592.     depth = level;
  593.   } else {
  594.     depth = 4;    /* 5, 6 手先読みは反復深化を使う */
  595.   }
  596.   for( ; depth <= level; depth++ ){
  597.     int i, point = (turn == BLACK ? MIN_LIMIT : MAX_LIMIT);
  598.     for( i = 0; i < limit; i++ ){
  599.       int value, pos = space[i];
  600.       char piece_buffer[SIZE/2];
  601.       if( board[pos] != FREE ) continue;
  602.  
  603.       /* 石を置く */
  604.       if( !reverse_piece( pos, turn, piece_buffer ) ) continue;
  605.       /* 終了チェック */
  606.       if( (value = result_value( FALSE )) == NO_VALUE ){
  607.     if( turn == BLACK ){
  608.       value = search_white( 1, point, FALSE );
  609.     } else {
  610.       value = search_black( 1, point, FALSE );
  611.     }
  612.       }
  613.       value_table[i] = value;
  614.       /* 元に戻す */
  615.       {
  616.     char *ptr = piece_buffer;
  617.     char piece = (turn == BLACK ? WHITE : BLACK);
  618.     white = save_white;
  619.     black = save_black;
  620.     board[pos] = FREE;
  621.     do {
  622.       board[*ptr++] = piece;
  623.     } while( *ptr != -1 );
  624.       }
  625.       if( (turn == BLACK && value > point) ||
  626.       (turn == WHITE && value < point) ){
  627.     point = value;
  628.       }
  629.     }
  630.     if( depth <= 4 ){
  631.       /* NO_VALUE を後ろに集める */
  632.       rsort( limit );
  633.       /* NO_VALUE を除外する */
  634.       while( value_table[limit - 1] == NO_VALUE ) limit--;
  635.     }
  636.     if( turn == BLACK ) sort( limit ); else rsort( limit );
  637.   }
  638. }
  639.  
  640. /* 読み切り */
  641. static void finish_move( int turn )
  642. {
  643.   int   limit = set_space_postion();
  644.   short save_white = white;
  645.   short save_black = black;
  646.   int   i, point = (turn == BLACK ? MIN_LIMIT : MAX_LIMIT);
  647.   for( i = 0; i < limit; i++ ){
  648.     int value, pos = space[i];
  649.     char piece_buffer[SIZE];
  650.  
  651.     /* 駒が置いてあるかチェックする */
  652.     if( board[pos] != FREE ) continue;
  653.     /* 駒を置く */
  654.     if( !reverse_piece( pos, turn, piece_buffer ) ) continue;
  655.  
  656.     /* 終了チェック */
  657.     if( black + white < SIZE ){
  658.       if( turn == BLACK ){
  659.     value = finish_white( point, FALSE );
  660.       } else {
  661.     value = finish_black( point, FALSE );
  662.       }
  663.     } else {
  664.       value = black - white;
  665.     }
  666.     value_table[i] = value;
  667.     /* 駒を元に戻す */
  668.     {
  669.       char *ptr = piece_buffer;
  670.       char piece = (turn == BLACK ? WHITE : BLACK);
  671.       board[pos] = FREE;
  672.       white = save_white;
  673.       black = save_black;
  674.       do {
  675.     board[*ptr++] = piece;
  676.       } while( *ptr != -1 );
  677.     }
  678.     if((turn == BLACK && value > point) ||
  679.        (turn == WHITE && value < point) ){
  680.       point = value;
  681.     }
  682.   }
  683.   /* NO_VALUE を後ろに集める */
  684.   rsort( limit );
  685.   /* NO_VALUE を除外する */
  686.   while( value_table[limit - 1] == NO_VALUE ) limit--;
  687.   if( turn == BLACK ) sort( limit ); else rsort( limit );
  688. }  
  689.  
  690.  
  691. /* 指手の決定 */
  692. static int decide_move( int turn )
  693. {
  694.   int move = 0, i = 1, v = value_table[0];
  695.   while( v == value_table[i] ) i++;
  696.   /* 同じ値の手がある */
  697.   if( i > 1 ){
  698.     /* 乱数で指手を決定する */
  699.     move = rand() % i;
  700.   }
  701.   return space[move];
  702. }
  703.  
  704. /* 反復深化による探索 */
  705. int select_move( int turn, int level )
  706. {
  707.   int num  = white + black;
  708.   static int finish_table[6] = {
  709.     7, 8, 9, 10, 11, 12,        /* 7 はダミー */
  710.   };
  711.   /* 重みの設定 */
  712.   if( num + level > 60 ){
  713.     w1 = 30; w2 = 20;
  714.   } else if( num + level > 30 ){
  715.     w1 = 20; w2 = 20;
  716.   } else {
  717.     w1 = 20; w2 = 10;
  718.   }
  719.   /* 読み切りモードのチェック */
  720.   if( (SIZE - num) <= finish_table[level] ){
  721.     finish_move( turn );
  722.   } else {
  723.     search_move( turn, level );
  724.   }
  725.   /* 指手の決定 */
  726.   return decide_move( turn );
  727. }
  728.  
  729. /* end of file */
  730.  
  731.